home *** CD-ROM | disk | FTP | other *** search
- /* File: ControlKeyPatch.c
-
- Description:
- routines for patching the ADB manager to simulate the control
- key being held down. This file contains routines for installing,
- removing and calling the control key patch. Client code
- can link with this file and place the patch resource in their
- resource fork.
-
- Author: John Montbriand
-
- Copyright:
- Copyright © 1999 by Apple Computer, Inc.
- All rights reserved worldwide.
-
- Disclaimer:
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Change History (most recent first):
- 27/8/99 created by John Montbriand
- */
-
-
- #include "ControlKeyPatch.h"
- #include <Resources.h>
- #include <Memory.h>
- #include <Errors.h>
-
-
- OSErr NewControlKeyPatch(Boolean inSysHeap, ControlKeyPatchPtr *patch) {
- ADBSetInfoBlock siBlock;
- ControlKeyPatchPtr patchResult;
- ControlKeyPatchSegment **patchSegData, *patchSegment;
- long patchsize, adbCount, i;
- KeyCmdCallUPP upHook, downHook;
- Boolean patchInstalled, sysheapActive;
- THz savedZone;
- OSErr err;
-
- /* set up locals to a known state */
- patchSegData = NULL;
- patchResult = NULL;
- patchSegment = NULL;
- upHook = downHook = NULL;
- patchInstalled = false;
- sysheapActive = false;
-
- /* get the patch resource */
- patchSegData = (ControlKeyPatchSegment **) GetResource('PROC', 128);
- if (patchSegData == NULL) { err = resNotFound; goto bail; }
- patchsize = GetHandleSize((Handle) patchSegData);
-
- /* set the memory manager heap to the target */
- if (inSysHeap) {
- savedZone = GetZone();
- SetZone(SystemZone());
- sysheapActive = true;
- }
-
- /* allocate our state variables */
- patchResult = (ControlKeyPatchPtr) NewPtrClear(sizeof(ControlKeyPatchVars));
- if (patchResult == NULL) { err = memFullErr; goto bail; }
- patchResult->downflag = 0;
- patchResult->systemPatch = inSysHeap;
-
- /* allocate the patch segment's storage */
- patchSegment = (ControlKeyPatchSegment *) NewPtr(patchsize);
- if (patchSegment == NULL) { err = memFullErr; goto bail; }
- BlockMove(*patchSegData, patchSegment, patchsize);
- patchResult->patchSegment = patchSegment;
-
- /* save pointers/routine descriptors for the callbacks */
- downHook = NewControlKeyCommandUPP(&patchSegment->downbranch);
- upHook = NewControlKeyCommandUPP(&patchSegment->upbranch);
- patchResult->SetKeyDownHook = downHook;
- patchResult->SetKeyUpHook = upHook;
-
- /* find the first keyboard and patch its service routine */
- adbCount = CountADBs();
- for ( i = 1; i <= adbCount; i++) {
- ADBDataBlock adbInfo;
- ADBAddress adbAddress;
- /* get the i'th ADB entry */
- adbAddress = GetIndADB(&adbInfo, i);
- if (adbAddress < 0) continue; /* no device in that entry */
- /* only process keyboards */
- if (adbInfo.origADBAddr == 2) {
- /* save the command address + talk code */
- patchResult->command = ((adbAddress<<4) | 0xC);
-
- /* the adb address */
- patchResult->adbAddress = adbAddress;
-
- /* save the service routines in the patch data */
- patchResult->originaljump = (long) adbInfo.dbServiceRtPtr;
- patchResult->originaldata = (long) adbInfo.dbDataAreaAddr;
-
- /* replace the device's service routine to call our patch */
- siBlock.siService = (ADBServiceRoutineUPP) patchSegment;
- siBlock.siDataAreaAddr = (Ptr) patchResult;
- SetADBInfo(&siBlock, adbAddress);
-
- /* exit */
- patchInstalled = true;
- break;
- }
- }
- if ( ! patchInstalled) { err = kErrNoKeyboardFound; goto bail; }
- /* restore the correct heap zone */
- if (sysheapActive) SetZone(savedZone);
- /* release the patch resource */
- ReleaseResource((Handle) patchSegData);
- /* return our patch state variables */
- *patch = patchResult;
- return noErr;
-
- bail:
- /* restore the service routine, if it was set */
- if (patchInstalled) {
- siBlock.siService = (ADBServiceRoutineUPP) patchResult->originaljump;
- siBlock.siDataAreaAddr = (Ptr) patchResult->originaldata;
- SetADBInfo(&siBlock, patchResult->adbAddress);
- }
- /* deallocate storage as necessary */
- if (patchSegment != NULL) DisposePtr((Ptr) patchSegment);
- if (patchResult != NULL) DisposePtr((Ptr) patchResult);
- if (upHook != NULL) DisposeControlKeyCommandUPP(upHook);
- if (downHook != NULL) DisposeControlKeyCommandUPP(downHook);
- /* restore the correct heap zone */
- if (sysheapActive) SetZone(savedZone);
- /* release the patch resource */
- if (patchSegData != NULL) ReleaseResource((Handle) patchSegData);
- return err;
- }
-
- void DisposeControlKeyPatch(ControlKeyPatchPtr patch) {
- ADBSetInfoBlock siBlock;
- /* make sure the key is up */
- CallControlKeyCommandUPP(patch->SetKeyUpHook, patch);
- /* restore the original service routine */
- siBlock.siService = (ADBServiceRoutineUPP) patch->originaljump;
- siBlock.siDataAreaAddr = (Ptr) patch->originaldata;
- SetADBInfo(&siBlock, patch->adbAddress);
- /*release any routine descriptors */
- DisposeControlKeyCommandUPP(patch->SetKeyDownHook);
- DisposeControlKeyCommandUPP(patch->SetKeyUpHook);
- /* dispose of the remaining storage */
- DisposePtr((Ptr) patch->patchSegment);
- DisposePtr((Ptr) patch);
- }
-
-
- OSErr ControlKeyPatchReInstall(ControlKeyPatchPtr patch) {
- long adbCount, i;
- Boolean patchInstalled;
-
- /* set up locals */
- patchInstalled = false;
-
- /* find the first keyboard and patch its service routine */
- adbCount = CountADBs();
- for ( i = 1; i <= adbCount; i++) {
- ADBDataBlock adbInfo;
- ADBAddress adbAddress;
- /* get the i'th ADB entry */
- adbAddress = GetIndADB(&adbInfo, i);
- if (adbAddress < 0) continue; /* no device in that entry */
- /* only process keyboards */
- if (adbInfo.origADBAddr == 2) {
- ADBSetInfoBlock siBlock;
- /* save the command address + talk code */
- patch->command = ((adbAddress<<4) | 0xC);
-
- /* the adb address */
- patch->adbAddress = adbAddress;
-
- /* save the service routines in the patch data */
- patch->originaljump = (long) adbInfo.dbServiceRtPtr;
- patch->originaldata = (long) adbInfo.dbDataAreaAddr;
-
- /* replace the device's service routine to call our patch */
- siBlock.siService = (ADBServiceRoutineUPP) patch->patchSegment;
- siBlock.siDataAreaAddr = (Ptr) patch;
- SetADBInfo(&siBlock, adbAddress);
-
- /* exit */
- patchInstalled = true;
- break;
- }
- }
- if ( ! patchInstalled)
- return kErrNoKeyboardFound;
- else return noErr;
- }
-
- void SetControlKeyDown(ControlKeyPatchPtr patch) {
- CallControlKeyCommandUPP(patch->SetKeyDownHook, patch);
- }
-
- void SetControlKeyUp(ControlKeyPatchPtr patch) {
- CallControlKeyCommandUPP(patch->SetKeyUpHook, patch);
- }
-